package demo.java.util.stream;

import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.junit.Test;

/**
 * 
 * @author hanjy
 *
 */
public class IntStreamDemo {

    static Random random = new Random();

    @Test
    public void demoIntStream() {
        // 随机10个int类型的流
        IntStream intStream = random.ints(10);
        // 计算列表中的元素数
        intStream.forEach(value -> System.out.print(value + "..."));
        System.out.println();
        List<Integer> list = random.ints(10).boxed().collect(Collectors.toList());
        // 计算列表中的元素数
        System.out.println("count()=" + list.stream().count());
        // 计算列表中元素的平均数
        Double avarage = list.stream().collect(Collectors.averagingInt(item -> item));
        System.out.println("avarage()=" + avarage);
        // 对列表元素进行统计
        IntSummaryStatistics intSummaryStatistics = list.stream().collect(Collectors.summarizingInt(value -> value));
        System.out.println("summarize = " + intSummaryStatistics);
        // 根据List创建Map
        Map<Integer, Integer> map = list.stream().collect(Collectors.toMap(p -> p, q -> q * 3));
        System.out.println("Collectors.toMap = " + map);
        // 求列表元素的最大数
        Optional<Integer> max = list.stream().reduce(Math::max);
        max.ifPresent(value -> System.out.println(value));
    }
    
    /**
     * local variables referenced from an inner class must be final or effectively final
     */
    @Test
    public void testForCircle() {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 5; i++) {
            int temp = i;

            executorService.submit(new Runnable() {
                public void run() {
                    System.out.println("Running task " + temp);
                }
            });
        }

        IntStream.range(0, 5).forEach(i -> executorService.submit(new Runnable() {
            public void run() {
                System.out.println("Running task " + i);
            }
        }));
        System.out.println("将内部类替换为拉姆达表达式");
        IntStream.range(0, 5).forEach(i -> executorService.submit(() -> System.out.println("Running task " + i)));

        executorService.shutdown();
    }

    /**
     * iterate 方法很容易使用；它只需获取一个初始值即可开始迭代。作为第二参数传入的拉姆达表达式决定了迭代中的下一个值。
     */
    @Test
    public void iterate() {
        System.out.println("跳过值");
        int total = 0;
        for (int i = 1; i <= 100; i = i + 3) {
            total += i;
        }
        System.out.println(total);

        total = IntStream.iterate(1, e -> e + 3).limit(34).sum();
        System.out.println(total);
        // 有条件的迭代
        /**
         * 与 takeWhile 方法相反的是 dropWhile，它跳过满足给定条件前的值，这两个方法都是 JDK 中非常需要的补充方法。
         * 
         * takeWhile 方法类似于 break，而 dropWhile 则类似于 continue。从 Java 9 开始，它们将可用于任何类型的 Stream。
         */
        IntStream.iterate(1, e -> e + 3)
                // .takeWhile(i -> i <= 100) //available in Java 9
                .sum();

        // 使用 iterate 的逆向迭代
        IntStream.iterate(7, e -> e - 1).limit(7);
    }

    /**
     * 测试FOR循环的替代方法
     */
    @Test
    public void range() {
        IntStream.range(0, 4).forEach(i -> System.out.print(i + "..."));
        System.out.println();
        IntStream.rangeClosed(0, 4).forEach(e -> System.out.print(e + "..."));
    }
}
